extends CanvasLayer
class_name UILayer

# ==================================================
# author: qlh
# description：
# 界面ui层控制器
# 提供UI的创建、销毁、跳转
# 当前层为UI层最后一个节点
# ==================================================

signal ui_close(ui)


#------------------变量区----------------------------
# 所有的UILayer 缓存实例共用同一个
const ui_cache = {}

# ui栈
const ui_statck = []

# 可以同时存在多个UI层
const layers = []

const data = {
	"cur_ui": null # 当前显示的ui
}



#方法区----------------------------------------------

var DramaSignalData
var MainDirectionSignal

var WebsocketUtils

func _init():
	# 添加进ui层
	layers.append(self)


# ==================================================
# 添加 UI
# @parm path: ui路径
# @parm pre_level: 上一层ui移除等级
# @parm cache: 是否缓存ui default：true
# return 返回加入的ui
# ==================================================
func add_ui(path, pre_level=1, cache=true):
	print_debug("ui add path:", path)

	# 获取加载ui
	var ui = get_ui(path, cache)

	add_instance(ui, pre_level)

	return ui


# ==================================================
# 添加 子节点UI，用于不添加到UI实例树中的UI
# @parm path: ui路径
# @parm pre_level: 上一层ui移除等级
# return 返回加入的ui
# ==================================================
func add_instance(ui, pre_level=0):
	var cur_ui = data["cur_ui"]
	
	var childrens = get_children()
	
	var back_ui = null
	if childrens.size() > 0:
		back_ui = childrens.back()
	
	
	if cur_ui != ui:
		ui.visible = true
		# 上一ui隐藏
		pop_ui(pre_level)
		
		# 加入UI栈
		ui_statck.append(ui)
		
		data["cur_ui"] = ui
		
		ui.set_meta("ui_layer", self)
		
		cur_ui = ui
		if ui.get_parent() != self:
			add_child(ui)

		if ui.has_method("state_update"):
			# 存在状态更新方法
			funcref(ui, "state_update").call_func()


	return ui


# ==================================================
# 注册UI到缓存里，可通过UILayer控制其状态更新
# 针对已存在节点树的UI
# @parm path: ui路径
# @parm ui: 注册的UI
# ==================================================
func register_ui(path, ui):
	ui.set_meta("path", path)
	print_debug("register ui:", path)

	ui_cache[path] = ui


# ==================================================
# 刷新存在UI的状态
# 及执行UI state_update方法
# @parm path_list: ui路径
# ==================================================
func state_update_ui(path_list):
	for path in path_list:
		var ui = ui_cache.get(path, null)
		if ui != null and ui.has_method("state_update"):
			# 存在状态更新方法
			funcref(ui, "state_update").call_func()




# 去除栈末尾为null的元素
func ui_statck_empty():
	while ui_statck.size() > 0 and (ui_statck.back() == null ||  ui_statck.back().is_queued_for_deletion()):
		ui_statck.pop_back()

# ==================================================
# 对上一层ui操作
# @parm level:  1 隐藏显示 2 移除当前ui 3 移除并销毁ui
# ==================================================
func pop_ui(level=2):
	ui_statck_empty()
		
	if not ui_statck.empty():
		var last_ui = ui_statck.back()

		if level > 1:
			emit_signal("ui_close", last_ui)

		# 隐藏显示
		if level == 1:
			print_debug("隐藏显示", last_ui)
			last_ui.visible = false

		# 移除
		if level >= 2:
			print_debug("移除ui", last_ui)
			ui_statck.pop_back()
			node_remove_ui(last_ui)
			
			# 让弹出后的最底层ui显示出来
			if ui_statck.size() > 0:
				var back = ui_statck.back()
				back.visible = true
				data["cur_ui"] = back
			else:
				data["cur_ui"] = null

			var path = last_ui.get_meta("path", "")
			
			if path != "" and ui_cache.get(path, null):
				# 单例缓存里的UI组件不可销毁
				pass
			else:
				# 等待60秒后自动清除 防止调用空实例
				yield(get_tree().create_timer(60),"timeout")
				# 不存在单例缓存里的UI组件不可销毁
				last_ui.queue_free()
			
		


# ==================================================
# 清空UI层所有ui
# @parm destroy:是否销毁当前ui
# ==================================================
func clear():
	for layer in layers:
		for ui in layer.get_children():
			layer.remove_child(ui)
	
	ui_statck.clear()
	data["cur_ui"] = null


# ==================================================
# 通过路径获取UI ，不存在则会初始化
# @parm path:path
# @parm cache:是否加入缓存
# ==================================================
func get_ui(path, cache=true):
	var ui = ui_cache.get(path, null)

	if ui == null:
		ui = load(path).instance()
		if cache:
			ui_cache[path] = ui

	ui.set_meta("path", path)

	return ui


# 通过路径获取UI ，不存在则会初始化
# ==================================================
func get_cache_ui(path):
	var ui = ui_cache.get(path, null)
	return ui


# ==================================================
# 判断UI栈里是否存在该 ui
# ==================================================
func stack_has_ui(ui):
	for child in get_children():
		if child == ui:
			return true

	return false




# ==============静态方法区=======================

# ==================================================
# 获取节点的UI层
# ==================================================
static func get_ui_Layer(node):
	return node.get_meta("ui_layer")
	


static func node_pop_ui(node, level=2):
	var ui_layer = get_ui_Layer(node)
	
	# 如果UI在栈顶
	if ui_statck.back() == node:
		ui_layer.pop_ui(level)
	else:
		# pass
		# 没有在栈顶
		var index = ui_statck.find(node)
		if index >= 0:
			ui_statck.remove(index)
		
		node_remove_ui(node, level)
		
		


static func node_remove_ui(node, level=2):
	var ui_layer = get_ui_Layer(node)
	if ui_layer:
		if node.get_parent() == ui_layer:
			ui_layer.remove_child(node)
		
		




